[% setvar title docs/pdds/pdd16_native_call.pod - NCI conventions and definitions %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='NAME'></a><h1>NAME</h1>
<p>docs/pdds/pdd16_native_call.pod - NCI conventions and definitions</p>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>This PDD describes the native call interface, and the function
signatures used to describe those functions.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<p>The NCI is designed to allow Parrot to interface to <i>most</i> of the
functions in a C library without having to write any C code for that
interface. It isn't designed to be a universal C-less
interface--there will always be libraries that have some bizarre
parameter list that requires that some C be written. It should,
however, handle all the simple cases.</p>
<p>Using the NCI, parrot automatically wraps the C functions and presents
them as prototyped subroutines that follow normal parrot calling
conventions, and can be called like any other parrot subroutine.</p>
<p>The NCI uses the platform native dynamic by-name function loading
mechanism (dlopen/dlsym on unix and LoadLibrary/GetProcAddress on
Win32, for example) to get the function pointer, then dynamically
generates the wrapper based on the signature of that function.</p>
<p>As there is no good platform-independent way to determine function
signatures (C header files are not always available (certainly not
for libraries not designed for access from C) and not always
reasonably parseable anyway, and there is no generic way to query a
function for its signature) the signature must be passed in when the
linkage between the C function and parrot is made.</p>
<a name='Function signatures'></a><h2>Function signatures</h2>
<p>The following list are the valid letters in the function signatures
for Parrot's NCI. Note that only letters and numbers are valid, and
each letter represents a single parameter passed into the NCI. Note
that the letters are case-sensitive, and must be within the base
7-bit ASCII character set.</p>
<p>At some point punctuation may be used as modifiers on the function
parameters, in which case each parameter may be represented by
multiple letters.</p>
<p>In <i>no</i> case should the signature letters be separated by
whitespace. This restriction may be lifted in the future, but for now
remains as an avenue for adding additional functionality.</p>
<ul>
<li><a name='Void. As a return type indicates that there is no return type. As a parameter indicates that there are no parameters. Can't be mixed with other parameter types.'></a>Void. As a return type indicates that there <i>is</i> no return type. As
a parameter indicates that there are no parameters. Can't be mixed
with other parameter types.</li>
<li><a name='Char. This is an integer type, taken from (or put into) an I register. NOTE: it might be signed or unsigned because that is how an unadorned C 'char' works.'></a>Char. This is an integer type, taken from (or put into) an I register.
NOTE: it might be signed or unsigned because that is how an unadorned
C 'char' works.</li>
<li><a name='short. An integer type, taken from or put into an I register. It is always signed, not unsigned.'></a>short. An integer type, taken from or put into an I register.
It is always signed, not unsigned.</li>
<li><a name='int. An integer type. It is always signed, not unsigned.'></a>int. An integer type.
It is always signed, not unsigned.</li>
<li><a name='long. An integer type. You know the drill. It is always signed, not unsigned.'></a>long. An integer type. You know the drill.
It is always signed, not unsigned.</li>
<li><a name='float. F register denizen.'></a>float. F register denizen.</li>
<li><a name='double. F register, double-precision floating point type'></a>double. F register, double-precision floating point type</li>
<li><a name='A PMC register.'></a>A PMC register.</li>
<li><a name='PMC thingie. A generic pointer, taken from or stuck into a PMC's data pointer. If this is a return type, parrot will create a new UnManagedStruct PMC type, which is just a generic &quot;pointer to some damn thing or other&quot; PMC type which Parrot does no management of.'></a>PMC thingie. A generic pointer, taken from or stuck into a PMC's
data pointer. If this is a return type, parrot will create a new
UnManagedStruct PMC type, which is just a generic &quot;pointer to some
damn thing or other&quot; PMC type which Parrot does <i>no</i> management of.</li>
<li><a name='2'></a>2</li>
<p>A pointer to a short, taken from an P register of an int-like PMC.
On return from NCI, the PMC_int_val will hold the new value.</p>
<li><a name='3'></a>3</li>
<p>A pointer to an int, taken from an P register of an int-like PMC.
On return from NCI, the PMC_int_val will hold the new value.</p>
<li><a name='4'></a>4</li>
<p>A pointer to a long, taken from an P register of an int-like PMC.
On return from NCI, the PMC_int_val will hold the new value.</p>
<li><a name='string pointer. Taken from, or stuck into, a string register. (Converted to a null-terminated C string before passing in)'></a>string pointer. Taken from, or stuck into, a string
register. (Converted to a null-terminated C string before passing in)</li>
<li><a name='This parameter is used for passing user data to a callback creation. More explanation in the callbacks section.'></a>This parameter is used for passing user data to a callback creation.
More explanation in the <i><a href='http://search.cpan.org/perldoc?callbacks'>callbacks</a></i> section.</li>
</ul>
<p>Note that not all types are valid as return types.</p>
<a name='Examples'></a><h2>Examples</h2>
<p>Most of the function parameters are reasonably self-evident. Some,
however, merit additional explanation. The</p>
<a name='Callbacks'></a><h2>Callbacks</h2>
<p>Some libraries, particularly ones implementing more complex
functionality such as databases or GUIs, want callbacks, that is ways
to call a function under the control of the library rather than under
control of the interpreter. These functions must be C functions, and
generally are passed parameters to indicate what should be done.</p>
<p>Unfortunately there's no good way to generically describe all
possible callback parameter sets, so in some cases hand-written C
will be necessary. However, many callback functions share a common
signature, and parrot provides some ready-made functions for this
purpose that should serve for most of the callback uses.</p>
<p>There are two callback functions, Parrot_callback_C and
Parrot_callback_D, which differ if the passed in <code>user_data</code> is
second or first respectively:</p>
<pre>   void (function *)(void *library_data, void *user_data);

   void (function *)(void *user_data, void *library_data);</pre>
<p>The information <code>library_data</code> is normally coming from C code and
can be any C type that Parrot supports as NCI value.</p>
<p>The position of the <code>user_data</code> is specified with the <code>U</code> function
signature, when creating the callback PMC:</p>
<pre>  cb_PMC = new_callback cb_Sub, user_data, &quot;tU&quot;</pre>
<!-- POD_ERROR: unterminated C<...> at line 168 in file pdd/pdd16_native_call.pod -->
<p>Given a Parrot function <code>cb_Sub</code>, and a <code>user_data</code> PMC, this creates
a callback PMC <code>cb_PMC</code>, which expects the user data as the second argument.
The information returned by the callback (<code>library_data) is a C string.</code></p>
<p>Since parrot needs more than just a pointer to a generic function to
figure out what to do, it stuffs all the extra information into the
<code>user_data</code> pointer, which contains a custom PMC holding all the
information that Parrot needs. This also implies that the C function
that installs the callback, must not make any assumptions on the <code>user_data</code>
argument. This argument must be handled transparently by the C code.</p>
<p>The callback function takes care of wrapping the external data
pointer into an UnManagedStruct PMC, the same as if it were a p
return type of a normal NCI function.</p>
<p>The signature of the <i>parrot</i> subroutine which is called by the
callback should be:</p>
<pre>   void parrotsub(PMC user_data, &lt;type&gt; external_data)</pre>
<p>The sequence for this is:</p>
<ul>
<li><a name='Step 1'></a>Step 1</li>
<p>Create a callback function.</p>
<pre>  new_callback CB_PMC, CB_SUB, USER_DATA, &quot;signature&quot;</pre>
<li><a name='Step 2'></a>Step 2</li>
<p>Register the callback</p>
<pre>  dlfunc C_FUNCTION, &quot;function_name&quot;, &quot;signature&quot;
  C_FUNCTION(CP_PMC, USER_DATA)</pre>
</ul>
<p>When the callback function is invoked by the external library, the
function itself should look like:</p>
<pre>  .sub _my_callback prototyped
    .param pmc my_data
    .param pmc library_data   # type depends on signature
    # Do something with the passed in data
  .end</pre>
<p>Parrot itself handles all the nasty bits involved in collecting up
the interpreter pointer, creating the wrapping PMCs, stuffing data
various places, and generally dealing with the bookkeeping.</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p><i><a href='http://search.cpan.org/perldoc?pdd06_pasm.pod'>pdd06_pasm.pod</a></i></p>
<a name='SEE ALSO'></a><h1>SEE ALSO</h1>
<p><i><a href='http://search.cpan.org/perldoc?t#pmc/nci.t'>&quot;pmc/nci.t&quot; in t</a></i>, <i><a href='http://search.cpan.org/perldoc?src#nci_test.c'>&quot;nci_test.c&quot; in src</a></i></p>
<a name='VERSION'></a><h1>VERSION</h1>
<a name='CURRENT'></a><h2>CURRENT</h2>
<pre>    Maintainer: Dan Sugalski
    Class: Internals
    PDD Number: 16
    Version: 1.1
    Status: Developing
    Last Modified: Oct 12, 2004
    PDD Format: 1
    Language: English</pre>
<a name='HISTORY'></a><h2>HISTORY</h2>
<ul>
<li><a name='version 1.1'></a>version 1.1</li>
<p>Changed callback section to reflect current status.</p>
<li><a name='version 1'></a>version 1</li>
<p>None. First version</p>
</ul>
<a name='CHANGES'></a><h1>CHANGES</h1>
<ul>
<li><a name='version 1.1'></a>version 1.1</li>
<p>Changed callback section to reflect current status.</p>
<li><a name='Version 1.0'></a>Version 1.0</li>
<p>None. First version</p>
</ul>
</div>
